#ifndef __CCNOTIFY_H__
#define __CCNOTIFY_H__

extern "C"
{
#include <sys/inotify.h>
}

#include <string>
#include <array>
#include <vector>
#include <unordered_map>
#include <map>
#include <functional>

namespace wb
{
using callback_t = std::function<void(inotify_event*)>;

//默认回调函数
struct DefaultCallback
{
    void operator()(inotify_event* e);
};

struct Event
{
    std::string path;
    uint32_t event;
    callback_t cb;
    int wfd;
};
// }  // namespace wb

// namespace std
// {
// struct hash<Event>
// {
//     std::size_t operator()(Event const& e) const
//     {
//         return std::hash<std::string>()(e.path);
//     }
// };
// }  // namespace std

// namespace wb
// {
class CCNotify
{
    enum : uint32_t
    {
        kEVENTSIZE = sizeof(inotify_event),
        kEVENTBUFSIZE = (kEVENTSIZE + 16) * 1024,
        kMAXEVENTS = 5000
    };

  public:
    CCNotify();
    ~CCNotify();

    CCNotify& operator=(CCNotify const&) = delete;
    CCNotify& operator=(CCNotify&&) = delete;
    CCNotify(CCNotify const&) = delete;
    CCNotify(CCNotify&&) = delete;

    enum : uint32_t
    {
        kAdd = 0,
        kMod = 1,
        kDel = 2,
        kACCESS = IN_ACCESS,
        kMODIFY = IN_MODIFY,
        kATTRIB = IN_ATTRIB,
        kCLOSE_WRITE = IN_CLOSE_WRITE,
        kCLOSE_NOWRITE = IN_CLOSE_NOWRITE,
        kCLOSE = IN_CLOSE,
        kOPEN = IN_OPEN,
        kMOVED_FROM = IN_MOVED_FROM,
        kMOVED_TO = IN_MOVED_TO,
        kMOVE = IN_MOVE,
        kCREATE = IN_CREATE,
        kDELETE = IN_DELETE,
        kDELETE_SELF = IN_DELETE_SELF,
        kMOVE_SELF = IN_MOVE_SELF,
    };

  public:
    void WatchCtl(uint32_t eventMask,
                  std::string const& path,
                  callback_t cb = DefaultCallback{},
                  uint32_t opt = kAdd);

    std::vector<Event*> WatchList();

    int Watch(std::vector<Event*>& events);

  private:
    int ifd_{-1};
    int efd_{-1};
    int watchingNum_{0};
    std::array<char, kEVENTBUFSIZE> eventBuffer_;
    std::unordered_map<std::string, int> wfdMap_;
};

}  // namespace wb

#endif  // __CCNOTIFY_H__